
// promise写一个ajax
function ajax(type, url, data) {
  return new Promise(function (resolve, reject) {
    let xhr = new XMLHttpRequest()
    xhr.open(type, url)
    xhr.onload = function () {
      if (this.status === 200) {
        resolve(this.response)
      } else {
        reject(new Error(this.statusText))
      }
    }
    xhr.send(data)
  })
}

// 生成器执行函数co
function co(generator) {
  const g = generator()
  function handleResult(result) {
    if (result.done) return
    result.value.then(data => {
      handleResult(g.next(data))
    }, error => {
      g.throw(error)
    })
  }
  handleResult(g.next())
}

// 简易promise
class MyPromise {
  constructor(fn) {
    this.status = "pending"
    this.resolve = undefined
    this.reject = undefined
    let resolve = (value) => {
      if (this.status = "pending") {
        this.status = "resolved"
        this.resolve = value
      }
    }
    let reject = (value) => {
      if (this.status = "pending") {
        this.status = "rejected"
        this.reject = value
      }
    }
    try {
      fn(resolve, reject)
    } catch (error) {
      reject(error)
    }
  }
  then(onResolved, onRejected) {
    switch (this.status) {
      case 'resolved': onResolved(this.resolve); break;
      case 'rejected': onRejected(this.resolve); break;
      default:
    }
  }
}

// Promise.all
function promiseAll(promises) {
  if (!Array.isArray(promises)) {
    throw new Error("promises must be an array")
  }
  return new Promise((resolve, reject) => {
    let n = promises.length
    let count = 0
    let proArr = []
    for (let i = 0; i < n; i++) {
      Promise.resolve(promises[i]).then(val => {
        proArr.push(val)
        count++
        if (count === n) {
          return resolve(proArr)
        }
      }, err => {
        return reject(err)
      })
    }
  })
}

// Promise.race
function promiseRace(promises) {
  if (!Array.isArray(promises)) {
    throw new Error("promises must be an array")
  }
  return new Promise((resolve, reject) => {
    for (let i = 0; i < n; i++) {
      Promise.resolve(promises[i]).then(val => {
        resolve(val)
      }, err => {
        reject(err)
      })
    }
  })
}

// 模拟实现一个 Promise.finally
function promiseFinally (cb) {
  return this.then(
    value => Promise.resolve(cb()).then(() => value),
    err => Promise.resolve(cb()).then(() => { throw err })
  )
}

// Promise.resolve
function promiseResolve (value) {
  if (value instanceof Promise) return value;
  return new Promise(resolve => resolve(value));
}